package utils

import (
	"bytes"
	"fmt"
)

func ArrayColumn(d []map[string]interface{}, columnKey string) []interface{} {
	nd := []interface{}{}
	for _, v := range d {
		nd = append(nd, v[columnKey])
	}
	return nd
}

func ArrayColumnIndex(d []map[string]interface{}, columnKey string, indexKey string) map[string]interface{} {
	nd := make(map[string]interface{})
	for _, v := range d {
		k := fmt.Sprintf("%v", v[indexKey])
		nd[k] = v[columnKey]
	}
	return nd
}

func InArray(needle interface{}, haystack []interface{}) bool {
	for _, v := range haystack {
		if fmt.Sprintf("%v", needle) == fmt.Sprintf("%v", v) {
			return true
		}
	}
	return false
}

func InArrayInt64(needle int64, haystack []int64) bool {
	for _, v := range haystack {
		if needle == v {
			return true
		}
	}
	return false
}

func ArrayKeysString(elements interface{}) []interface{} {
	elems := elements.(map[string]interface{})
	keys := make([]interface{}, len(elems))
	for key := range elems {
		keys = append(keys, key)
	}
	return keys
}

func ArrayDiff(arr1 []interface{}, arrs ...[]interface{}) (data []interface{}) {
	if len(arrs) == 0 {
		return arr1
	}
	i := 0
loop:
	for {
		if i == len(arr1) {
			break
		}
		v := arr1[i]
		for _, arr := range arrs {
			for _, val := range arr {
				if fmt.Sprintf("%v", v) == fmt.Sprintf("%v", val) {
					i++
					continue loop
				}
			}
		}
		data = append(data, v)
		i++
	}
	return

}

func ArrayFilter(haystack []interface{}, callback func(val interface{}) bool) []interface{} {
	nhaystack := []interface{}{}
	for _, v := range haystack {
		if callback(v) {
			nhaystack = append(nhaystack, v)
		}
	}
	return nhaystack
}

func ArrayIntersect(array1, array2 []interface{}) (array []interface{}) {
	hash := map[interface{}]bool{}
	for _, v := range array1 {
		hash[v] = true
	}

	for _, v := range array2 {
		if hash[v] {
			array = append(array, v)
		}
	}

	return
}

func Implode(glue string, pieces []string) string {
	var buf bytes.Buffer
	l := len(pieces)
	for _, str := range pieces {
		buf.WriteString(str)
		if l--; l > 0 {
			buf.WriteString(glue)
		}
	}
	return buf.String()
}
